package com.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DeckPanel;
import com.google.gwt.user.client.ui.DecoratorPanel;
import com.google.gwt.user.client.ui.DisclosurePanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.MultiWordSuggestOracle;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.SuggestBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.datepicker.client.DateBox;
import com.google.gwt.visualization.client.AjaxLoader;
import com.google.gwt.visualization.client.DataTable;
import com.google.gwt.visualization.client.LegendPosition;
import com.google.gwt.visualization.client.Query;
import com.google.gwt.visualization.client.QueryResponse;
import com.google.gwt.visualization.client.Query.Callback;
import com.google.gwt.visualization.client.visualizations.ColumnChart;
import com.google.gwt.visualization.client.visualizations.Table;


/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class CNStatsFront implements EntryPoint {

	private VerticalPanel plMain = new VerticalPanel();
	private FlexTable ftHeader = new FlexTable();
	
	private DeckPanel plBody = new DeckPanel();
	private VerticalPanel plSearch = new VerticalPanel();
	private DecoratorPanel dplSearch = new DecoratorPanel();
	private FlexTable ftSearch = new FlexTable();
	private SuggestBox sbTags;
	private Button btnSearch = new Button("Search", new ClkSearch());
	private DisclosurePanel plAdv = new DisclosurePanel("Advanced");
	private Grid gAdvSearch = new Grid(7, 7);
	private ListBox lbTags = new ListBox(true);
	private DateBox dbBegin = new DateBox();
	private DateBox dbEnd = new DateBox();
	private TextBox tbDfmt = new TextBox();
	private TextBox tbX = new TextBox();
	private TextBox tbY = new TextBox();
	private Button btnAdvSearch = new Button("Search", new ClkAdvSearch());
	
	private VerticalPanel plCharts = new VerticalPanel();
	private DecoratorPanel dplCharts = new DecoratorPanel();
	private Button btnBack = new Button("Back to Search", new ClickHandler() {
		public void onClick(ClickEvent event) {
			plBody.showWidget(0);
		}
	});
		
	private ColumnChart chCol;

//	private String baseURL = "http://localhost:8080/";
	private String baseURL = "http://cndata4u.appspot.com/";

  /**
   * This is the entry point method.
   */
  public void onModuleLoad() {
  	plMain.setPixelSize(Window.getClientWidth(), Window.getClientHeight());
  	plMain.add(ftHeader);
  	plMain.add(plBody);

  	plBody.setPixelSize(Window.getClientWidth(), Window.getClientHeight());
  	plBody.add(plSearch);
  	plBody.add(plCharts);
  	plBody.setAnimationEnabled(true);
  	
  	plSearch.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
  	plSearch.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
  	
  	plSearch.add(dplSearch);
  	dplSearch.add(ftSearch);
  	ftSearch.setHTML(0, 0, "Tags:");
  	ftSearch.setHTML(0, 1, "Loading...");
  	ftSearch.setWidget(0, 2, btnSearch);
  	ftSearch.getFlexCellFormatter().setColSpan(1, 0, 3);
  	ftSearch.setWidget(1, 0, plAdv);
  	plAdv.setContent(gAdvSearch);
  	plAdv.setAnimationEnabled(true);
  	
  	gAdvSearch.setHTML(0, 0, "Tags:");
  	gAdvSearch.setWidget(0, 1, lbTags);
  	lbTags.setVisibleItemCount(10);
  	gAdvSearch.setHTML(1, 0, "Begin:");
  	gAdvSearch.setWidget(1, 1, dbBegin);
  	gAdvSearch.setHTML(2, 0, "End:");
  	gAdvSearch.setWidget(2, 1, dbEnd);
  	gAdvSearch.setHTML(3, 0, "Format:");
  	gAdvSearch.setWidget(3, 1, tbDfmt);
  	gAdvSearch.setHTML(4, 0, "X:");
  	gAdvSearch.setWidget(4, 1, tbX);
  	gAdvSearch.setHTML(5, 0, "Y:");
  	gAdvSearch.setWidget(5, 1, tbY);
  	gAdvSearch.setWidget(6, 1, btnAdvSearch);
  	
  	gAdvSearch.getCellFormatter().setVerticalAlignment(0, 0, HasVerticalAlignment.ALIGN_TOP);
  	gAdvSearch.getCellFormatter().setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_RIGHT);
  	gAdvSearch.getCellFormatter().setHorizontalAlignment(1, 0, HasHorizontalAlignment.ALIGN_RIGHT);
  	gAdvSearch.getCellFormatter().setHorizontalAlignment(2, 0, HasHorizontalAlignment.ALIGN_RIGHT);
  	gAdvSearch.getCellFormatter().setHorizontalAlignment(3, 0, HasHorizontalAlignment.ALIGN_RIGHT);
  	gAdvSearch.getCellFormatter().setHorizontalAlignment(4, 0, HasHorizontalAlignment.ALIGN_RIGHT);
  	gAdvSearch.getCellFormatter().setHorizontalAlignment(5, 0, HasHorizontalAlignment.ALIGN_RIGHT);
  	gAdvSearch.getCellFormatter().setHorizontalAlignment(6, 1, HasHorizontalAlignment.ALIGN_RIGHT);
  	
  	plCharts.add(dplCharts);
  	plCharts.setCellHorizontalAlignment(dplCharts, HasHorizontalAlignment.ALIGN_CENTER);
  	plCharts.setCellVerticalAlignment(dplCharts, HasVerticalAlignment.ALIGN_MIDDLE);
  	plCharts.add(btnBack);
  	plCharts.setCellHorizontalAlignment(btnBack, HasHorizontalAlignment.ALIGN_CENTER);
  	plCharts.setCellVerticalAlignment(btnBack, HasVerticalAlignment.ALIGN_TOP);  	
  	  	
  	RootPanel.get().add(plMain);
  	
		AjaxLoader.loadVisualizationApi(new VisLoaded(), 
				ColumnChart.PACKAGE,
				Table.PACKAGE);	
		Window.addResizeHandler(new ResizeHandler(){
			public void onResize(ResizeEvent event){				
				plMain.setPixelSize(event.getWidth(), event.getHeight());
				plBody.setPixelSize(event.getWidth(), event.getHeight());
			}
		});
		
	}
  
  private final class ClkSearch implements ClickHandler {
		public void onClick(ClickEvent event) {
			String searchURL = baseURL + "querystats?tags=" + sbTags.getText().toLowerCase();
			sbTags.setText("e.g. Domestic GDP");
			Query.create(searchURL).send(new CBQueryStats());
		}
	}
	
	private final class ClkAdvSearch implements ClickHandler {
		public void onClick(ClickEvent event) {
			plAdv.setOpen(false);
			
			String tags = "";
			for(int i=lbTags.getSelectedIndex();i<lbTags.getItemCount();i++) {
				if(true == lbTags.isItemSelected(i)) {
					if(tags.length()>0) tags += " ";
					tags += lbTags.getValue(i);
				}
			}
			String searchURL = baseURL + "querystats?tags=" + tags;
			
			DateTimeFormat dfmt = DateTimeFormat.getFormat("yyyyMMddHHmmss");
			if(null != dbBegin.getValue()) {
				searchURL += "&begin=" + dfmt.format(dbBegin.getValue());
			}
			if(null != dbEnd.getValue()) {
				searchURL += "&end=" + dfmt.format(dbEnd.getValue());
			}
			if(tbDfmt.getValue().length() > 0) {
				searchURL += "&dfmt=" + tbDfmt.getValue();
			}
			if(tbX.getValue().length() > 0) {
				searchURL += "&x=" + tbX.getValue();
			}
			if(tbY.getValue().length() > 0) {
				searchURL += "&y=" + tbY.getValue();
			}
			Query.create(searchURL).send(new CBQueryStats());
		}
	}

	private final class CBQueryStats implements Callback {
		public void onResponse(QueryResponse response) {
			if (response.isError()) {
				Window.alert(response.getMessage()+":"+response.getDetailedMessage());
			} else {
				// Get the data from the QueryResponse.
				DataTable data = response.getDataTable();
				chCol.draw(data, createOptions());
				plBody.showWidget(1);
			}
		}
	}

	private final class CBQueryHistory implements Callback {
		public void onResponse(QueryResponse response) {
			if (response.isError()) {
				Window.alert(response.getMessage()+":"+response.getDetailedMessage());
			} else {
				DataTable data = response.getDataTable();
				
				MultiWordSuggestOracle oracle = new MultiWordSuggestOracle();
				for(int i=0; i<data.getNumberOfRows(); i++) {
					oracle.add(data.getValueString(i, 0));
				}
				sbTags = new SuggestBox(oracle);
				sbTags.setText("e.g. Domestic GDP");
				sbTags.getTextBox().addFocusHandler(new FocusHandler() {
					public void onFocus(FocusEvent event) {
						sbTags.setText("");
					}					
				});
				sbTags.getTextBox().addKeyPressHandler(new KeyPressHandler() {
					public void onKeyPress(KeyPressEvent event) {
						//Get return key
						if( sbTags.getText().length() > 0 &&
								13 == event.getCharCode()) {
							btnSearch.click();
						}
					}
				});
				sbTags.setAnimationEnabled(true);
				ftSearch.setWidget(0, 1, sbTags);
			}
		}
	}

	private final class CBQueryTags implements Callback {
		public void onResponse(QueryResponse response) {
			if (response.isError()) {
				Window.alert(response.getMessage()+":"+response.getDetailedMessage());
			} else {
				// Get the data from the QueryResponse.
				DataTable data = response.getDataTable();
				
				for(int i=0; i<data.getNumberOfRows(); i++) {
					lbTags.addItem(data.getValueString(i, 0));
				}
			}
		}
	}

	private final class VisLoaded implements Runnable {
		public void run() {
			Query.create(baseURL + "queryhistory").send(new CBQueryHistory());
			Query.create(baseURL + "querytags").send(new CBQueryTags());
			
			//Add ColumnChart
			chCol = new ColumnChart();
			dplCharts.add(chCol);
			plBody.showWidget(0);
			
			//Add Table
//			table = new Table();
//			dpBody.add(table, "Table");
		}
	}
	
	private ColumnChart.Options createOptions() {
		ColumnChart.Options options = ColumnChart.Options.create();
		double scale = 0.6;
		options.setSize((int)(Window.getClientWidth()*scale), 
				(int)(Window.getClientHeight()*scale));
		options.setLegend(LegendPosition.BOTTOM);
		return options;
	}
}


